
#include <BList>
#include <BTimer>
#include "member_BTimer.h"

using namespace BWE;

#define member						(*(member_BTimer*)_ptr)
#define member_allocate()			_ptr = new member_BTimer(this)
#define member_release()			delete (member_BTimer*)_ptr

BList<BTimerHolder>	g_timer_list;

#ifdef _LINUX_
#include <time.h>
#include <signal.h>
#include <stdio.h>

/* Function used for thread notification (SIGEV_THREAD) */
void timer_notify (union sigval)
{
	puts("Clock Notify ***************************");
}

BTimer::BTimer(int interval)
{
	member_allocate();
	sigevent se;
	se.sigev_notify = SIGEV_SIGNAL;//SIGEV_THREAD
	se.sigev_signo = SI_TIMER;
	se.sigev_value.sival_ptr = this;
	se.sigev_notify_function = timer_notify;
	se.sigev_notify_attributes = NULL;
	int ret = timer_create(CLOCK_REALTIME, &se, &member.timer);
}
BTimer::~BTimer()
{
	if(member.timer)
		timer_delete(member.timer);
	member_release();
}
void BTimer::setInterval(int interval)
{
	if(member.interval != interval)
	{
		member.interval = interval;
	}
}
int BTimer::interval() const
{
	return member.interval;
}
void BTimer::setCount(int count)
{
	if(member.count != count)
	{
		member.count = count;
	}
}
int BTimer::count() const
{
	return member.count;
}
bool BTimer::start()
{
	if(!member.timer)
		return false;

	itimerspec ts;
	ts.it_value.tv_sec = 0;
	ts.it_value.tv_nsec = member.count;
	ts.it_interval.tv_sec = 0;
	ts.it_interval.tv_nsec = member.interval;
	int ret = timer_settime(member.timer, 0, &ts, 0);
	if(ret == -1)
		return false;
	member.started = true;
	return true;
}
bool BTimer::stop()
{
	itimerspec ts;
	ts.it_value.tv_sec = 0;
	ts.it_value.tv_nsec = 0;
	ts.it_interval.tv_sec = 0;
	ts.it_interval.tv_nsec = 0;
	int ret = timer_settime(member.timer, 0, &ts, 0);
	if(ret == -1)
		return false;
	member.started = false;
	return true;
}

#endif

#ifdef _WINDOWS_SYSTEM_

VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
	for (BList<BTimerHolder>::iterator it = g_timer_list.begin(); it != g_timer_list.end(); it++)
	{
		BTimer* timer = it.value().ptr();
		if (timer_member(timer)->handle == idEvent)
		{
			timer_member(timer)->procTimerEvent(uMsg, dwTime);
			break;
		}
	}
}
BTimer::BTimer(int interval)
{
	g_timer_list.append(this);
	member_allocate();
	member.interval = interval;
}
BTimer::~BTimer()
{
	if (member.handle)
		KillTimer(0, member.handle);
	member_release();
	g_timer_list.remove(this);
}

void BTimer::setInterval(int interval)
{
	member.interval = interval;
}
int BTimer::interval() const
{
	return member.interval;
}

void BTimer::setCount(int count)
{
	member.count = count;
}
int BTimer::count() const
{
	return member.count;
}

bool BTimer::start()
{
	if (member.count == 0)
		return false;
	member.handle = SetTimer(0, member.handle, member.interval, TimerProc);
	return member.handle;
}
bool BTimer::stop()
{
	bool ret = KillTimer(0, member.handle);
	member.handle = 0;
	return ret;
}

#endif
